<?php

namespace app\common\service\core;

use app\common\enums\AccountTypeEnum;
use app\common\enums\BrokerageBusinessTypeEnum;
use app\common\enums\core\WithdrawStateEnum;
use app\common\enums\CourseFullTypeEnum;
use app\common\model\banxi\core\CoreBrokerageRw;
use app\common\model\banxi\core\CoreBrokerageWithdraw;
use app\common\model\banxi\learn\LearnSkRecord;
use app\common\model\banxi\organization\Organization;
use app\common\model\banxi\organization\OrganizationLevelConfig;
use app\common\model\banxi\student\Student;
use app\common\service\ApiService;
use app\common\service\ConfigService;
use app\common\service\SnowflakeService;
use ba\Exception;
use think\db\exception\PDOException;
use think\exception\ValidateException;
use think\facade\Db;

class BrokerageService extends ApiService
{

    private $brokerageType = ["", "直推", "间推"];

    /**
     * 提现审核
     */
    public function withdrawAudit($withdrawId, $result, $rejectReason, $payVoucher)
    {
        Db::startTrans();
        try {
            $coreBrokerageWithdraw = new CoreBrokerageWithdraw();
            $withdraw = $coreBrokerageWithdraw->where('id', $withdrawId)->find();
            if (empty($withdraw)) {
                throw new ValidateException('提现记录不存在');
            }
            $status = $withdraw['status'];
            if ($withdraw['status'] == WithdrawStateEnum::E2) {
                throw new ValidateException('该提现记录已打款');
            }
            if ($withdraw['status'] == WithdrawStateEnum::E3) {
                throw new ValidateException('该提现记录已被驳回');
            }
            $update = [];
            if ($result) {
                $update['payVoucher'] = $payVoucher;
                $update['status'] = WithdrawStateEnum::E2;
                $update['rejectReason'] = '';
            } else {
                $update['status'] = WithdrawStateEnum::E3;
                $update['rejectReason'] = $rejectReason;
                $coreBrokerageRw = new CoreBrokerageRw();
                $coreBrokerageRw->refundAccount($withdraw['brokerageFlowId'], '佣金提现驳回');
            }
            $coreBrokerageWithdraw->update($update, [
                'id' => $withdrawId,
                'status' => $status
            ]);
            Db::commit();
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
        return true;

    }


    public function withdrawApply($amount, $organizationId)
    {
        Db::startTrans();
        try {
            if (bccomp($amount, 0) <= 0) {
                throw new ValidateException('提现金额必须大于0');
            }
            $configService = new ConfigService();
            $minWithdrawMoney = $configService->getSysConfigValue('min_withdraw_money') ?? 20;
            if ($amount < $minWithdrawMoney) {
                $this->setError("提现金额不能小于$minWithdrawMoney");
                return false;
            }

            $organizationModel = new Organization();
            $organizationInfo = $organizationModel->where(['id' => $organizationId])->find();
            if (empty($organizationInfo)) {
                throw new ValidateException('机构不存在');
            }
            $snowflakeService = new SnowflakeService(1, 1);
            $withdrawId = $snowflakeService->nextId();
            $brokerageFlowId = $snowflakeService->nextId();
            $withdrawModel = new CoreBrokerageWithdraw();
            $withdrawModel->save([
                'id' => $withdrawId,
                'organizationId' => $organizationId,
                'amount' => $amount,
                'openBank' => $organizationInfo['openBank'],
                'openName' => $organizationInfo['openName'],
                'cardNo' => $organizationInfo['cardNo'],
                'brokerageFlowId' => $brokerageFlowId,
                'status' => WithdrawStateEnum::E1,
            ]);

            $coreBrokerageRw = new CoreBrokerageRw();
            $coreBrokerageRw->updateAccount([
                'id' => $brokerageFlowId,
                'accountId' => $organizationId,
                'accountType' => AccountTypeEnum::ORGAN,
                'organizationId' => $organizationId,
                'businessType' => BrokerageBusinessTypeEnum::E2,
                'businessId' => $withdrawId,
                'value' => $amount,
                'describe' => "佣金提现"
            ]);
            Db::commit();
        } catch (Exception|PDOException|ValidateException $e) {
            Db::rollback();
            $this->setError($e->getMessage());
            return false;
        }
        return true;
    }

    /**
     * 处理机构分佣
     *
     * @param string $message 消息内容
     * @return void
     */
    public function handleBrokerage($message)
    {
        // 解析消息
        $brokerageMessage = $message;
        //        $brokerageMessage = json_decode($message, true);
        //        if (empty($brokerageMessage)) {
        //            return;
        //        }

        $organizationId = $brokerageMessage['organizationId'] ?? '';

        // 检查是否为父级机构
        if (0 == $organizationId) {
            return;
        }

        $courseFullType = $brokerageMessage['courseFullType'] ?? '';
        $skRecordId = $brokerageMessage['skRecordId'] ?? 0;

        // 如果是体验课，直接返回
        if ($courseFullType == CourseFullTypeEnum::EXPERIENCE) {
            return;
        }

        // 获取上课记录
        $LearnSkRecordModel = new LearnSkRecord();
        $learnSkRecord = $LearnSkRecordModel->where('id', $skRecordId)->find();
        if (empty($learnSkRecord)) {
            throw new ValidateException("上课记录不存在");
        }

        if (!$learnSkRecord['isEnd']) {
            throw new ValidateException("上课未结束");
        }

        $studentId = $learnSkRecord['studentId'];
        $studentName = Student::getNameById($studentId);
        $studentName = !$studentName ? "【已删除】" : "【{$studentName}】";

        // 获取机构信息
        $OrganizationModel = new Organization();
        $organization1 = $OrganizationModel->where('id', $organizationId)->find();
        if (empty($organization1)) {
            throw new ValidateException("机构不存在");
        }

        $organizationId2 = $organization1['parentId'];
        $organization2 = $OrganizationModel->where('id', $organizationId2)->find();

        $organizationId3 = null;
        $organization3 = null;
        if (!empty($organization2)) {
            $organizationId3 = $organization2['parentId'];
            $organization3 = $OrganizationModel->where('id', $organizationId3)->find();
        }

        // 获取机构等级配置列表
        $OrganizationLevelConfigModel = new OrganizationLevelConfig();
        $levelConfigList = $OrganizationLevelConfigModel->select()->toArray();

        // 构建机构列表
        $organizationList = [];
        $organizationList[] = $organization1;
        if (!empty($organization2)) {
            $organizationList[] = $organization2;
        }
        if (!empty($organization3)) {
            $organizationList[] = $organization3;
        }

        // 遍历机构列表处理佣金
        for ($i = 0; $i < count($organizationList); $i++) {
            $organization = $organizationList[$i];

            // 构建描述信息
            $describeSb = '';
            if (isset($this->brokerageType[$i])) {
                $describeSb .= $this->brokerageType[$i];
            }

            if ($i == 0) {
                $describeSb .= $studentName;
            } else {
                $organizationTop = $organizationList[$i - 1];
                $describeSb .= "【{$organizationTop['name']}】学员";
            }
            $describeSb .= "上课获得佣金";

            $organizationIdSelf = $organization['id'];
            $level = $organization['level'];

            // 查找对应等级配置
            $levelConfig = null;
            foreach ($levelConfigList as $item) {
                if (isset($item['id']) && $item['id'] == $level) {
                    $levelConfig = $item;
                    break;
                }
            }

            // 获取金额
            $amount = $this->getLevelConfigAmount($levelConfig, $courseFullType, $i);

            // 如果金额大于0，则更新账户
            if ($amount > 0) {
                $trade = [
                    'describe' => $describeSb,
                    'accountId' => $organizationIdSelf,
                    'accountType' => AccountTypeEnum::ORGAN, // 对应 AccountType.ORGAN
                    'organizationId' => $organizationIdSelf,
                    'businessType' => BrokerageBusinessTypeEnum::E1, // 对应 BrokerageBusinessType.E1
                    'businessId' => $skRecordId,
                    'value' => $amount
                ];
                $CoreBrokerageRwModel = new CoreBrokerageRw();
                $CoreBrokerageRwModel->updateAccount($trade);
            }
        }
    }

    /**
     * 获取分佣金额
     *
     * @param array|null $levelConfig 机构等级配置
     * @param string $courseFullType 课程完整类型
     * @param int $type 0 自身 1 直推 2 间推
     * @return float 佣金金额
     * @throws Exception
     */
    private function getLevelConfigAmount($levelConfig, $courseFullType, $type)
    {
        // 检查机构等级配置是否存在
        if (empty($levelConfig)) {
            throw new ValidateException("机构等级配置不存在");
        }

        switch ($courseFullType) {
            case CourseFullTypeEnum::C_30:
                if ($type == 0) {
                    return isset($levelConfig['brokerage30Amount']) ? (float)$levelConfig['brokerage30Amount'] : 0;
                } else if ($type == 1) {
                    return isset($levelConfig['directBrokerage30Amount']) ? (float)$levelConfig['directBrokerage30Amount'] : 0;
                } else if ($type == 2) {
                    return isset($levelConfig['indirectBrokerage30Amount']) ? (float)$levelConfig['indirectBrokerage30Amount'] : 0;
                }
                break;
            case CourseFullTypeEnum::C_60:
                if ($type == 0) {
                    return isset($levelConfig['brokerage60Amount']) ? (float)$levelConfig['brokerage60Amount'] : 0;
                } else if ($type == 1) {
                    return isset($levelConfig['directBrokerage60Amount']) ? (float)$levelConfig['directBrokerage60Amount'] : 0;
                } else if ($type == 2) {
                    return isset($levelConfig['indirectBrokerage60Amount']) ? (float)$levelConfig['indirectBrokerage60Amount'] : 0;
                }
                break;
        }

        return 0;
    }
}
